#include "uart.h"

void UART1_Init(void)
{
    // 0. 引脚复用
    UART_Pin_Init();
    // 1. 配置UART1模块时钟为80MHz,提供波特率的基准时钟
    // 1.1 CCM_CSCDR1 bit[6]:配置时钟源为80MHz
    // 1.2 由UART模块时钟树配置分频系数为1  CCM_CSCDR1 bit[5:0]:000000
    CCM->CSCDR1 &= ~(0x1 << 6);
    CCM->CSCDR1 &= ~(0x3F << 0);

    // 2.1 软件复位 UARTx_UCR2 bit[0]:0
    UART1->UCR2 &= ~(0x1 << 0);
    // 等待复位完成 UARTx_UTS bit[0] 1:active 0:inactive
    while ((UART1->UTS) & (0x1 << 0))
        ;

    // 2.2 禁用波特率自动检测并关闭UART模块
    UART1->UCR1 = 0x00000000;

    // 3. 配置数据宽度 停止位宽度 无校验位 禁止硬件流控
    // 3.1 接收器使能 UARTx_UCR2 bit[1]:1
    UART1->UCR2 |= (0x1 << 1);
    // 3.2 发送器使能 UARTx_UCR2 bit[2]:1
    UART1->UCR2 |= (0x1 << 2);
    // 3.3 设置数据位宽度位8位 UARTx_UCR2 bit[5]:1
    UART1->UCR2 |= (0x1 << 5);
    // 3.4 设置停止位宽度为1位 UARTx_UCR2 bit[6]:0
    UART1->UCR2 &= ~(0x1 << 6);
    // 3.5 关闭奇偶校验 UARTx_UCR2 bit[8]:0
    UART1->UCR2 &= ~(0x1 << 8);
    // 3.6 忽略硬件流控 UARTx_UCR2 bit[14]:1
    UART1->UCR2 |= (0x1 << 14);

    // 4. UART默认工作在MUXED模式,置1以确保正确路由
    // UARTx_UCR3 bit[2]:1
    UART1->UCR3 |= (0x1 << 2);

    // 5. 设置波特率为115200
    // 5.1 设置ref_clk为80MHz,分频系数为1分频
    // UARTx_UFCR bit[9:7]: 101
    UART1->UFCR &= ~(0x7 << 7);
    UART1->UFCR |= (0x5 << 7);

    // 5.2 配置brm_clk，必须先写UBIR，再写UBMR
    // 5.2.1 设置UBIR寄存器值为71
    UART1->UBIR = 0x47;
    // 5.2.2 设置UBMR寄存器值为3124
    UART1->UBMR = 0xC34;

    // 6. 使能UART1模块
    UART1->UCR1 |= (0x1 << 0);
}

void UART_Pin_Init(void)
{
    // 1. 设置引脚复用为串口接收与发送引脚
    IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0);
    IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0);

    // 2.  配置引脚电气属性
    // 2.1 配置发送引脚电气属性
    IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);
    // 2.2 配置接收引脚电气属性
    IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
}

void UART1_SendByte(uint8_t byte)
{
    // 1. 判断上次发送是否完成 UARTx_USR2 bit[3]
    //  0代表发送未完成 1代表发送完成
    while (((UART1->USR2) >> 3) & (0x1) == 0)
        ;

    // 2. 发送数据 UARTx_UTXD bit[7:0]:存储待发送的数据
    UART1->UTXD = byte;
}

uint8_t UART1_ReceiveByte(void)
{
    // 1. 判断接收缓冲区是否为空,为空等待
    // UARTx_USR2 bit[0]: 0代表接收缓冲区无数据 1代表接收缓冲区至少存在1Byte数据
    while ((UART1->USR2) & (0x1) == 0)
        ;

    // 2. 读取数据 UARTx_URXD bit[7:0]
    uint32_t tmp = UART1->URXD;
    uint8_t ret = (tmp & 0xFF);
    return ret;
}

// 发送字符串
void UART1_SendString(char *str)
{
    char *pos = str;
    while (*pos)
    {
        UART1_SendByte((*pos));
        pos++;
    }
}

void putc(unsigned char ch)
{
    // 1. 判断上次发送是否完成 UARTx_USR2 bit[3]
    //  0代表发送未完成 1代表发送完成
    while (((UART1->USR2) >> 3) & (0x1) == 0)
        ;

    // 2. 发送数据 UARTx_UTXD bit[7:0]:存储待发送的数据
    UART1->UTXD = ch;
}

void puts(char *str)
{
    char *pos = str;
    while (*pos)
    {
        putc((*pos));
        pos++;
    }
}

unsigned char getc(void)
{
    // 1. 判断接收缓冲区是否为空,为空等待
    // UARTx_USR2 bit[0]: 0代表接收缓冲区无数据 1代表接收缓冲区至少存在1Byte数据
    while ((UART1->USR2) & (0x1) == 0)
        ;

    // 2. 读取数据 UARTx_URXD bit[7:0]
    uint32_t tmp = UART1->URXD;
    unsigned char ret = (unsigned char)(tmp & 0xFF);
    return ret;
}

void gets(char *str)
{
    unsigned char data;
    while ((data = getc()) != '\r')
    {
        *str++ = data;
    }
    //Linux系统回车换行为  \r\n
    //windows系统回车换行为 \n
    if (data == '\r')
    {
        *str++ = '\n';
        *str = '\0';
    }
}
